﻿using System;
using System.Collections.Generic;

using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Net;
using Lidgren.Network;
using RebellionII.GameObjects;
using RebellionII.GameObjects.Map;
using RebEngine.GameComponents;
using RebellionII.GameObjects.Units;
using RebellionII.GameObjects.Units.Instances;

namespace RebEngine.Managers
{
    public class NetServerManager : GameComponent
    {
        public static NetServer Server { set; get; }
        private static NetPeerConfiguration config;
        public static bool IsInitialized { set; get; }

        public static Universe gameUniverse;
        public static Team[] theTeams = new Team[5];

        public static Dictionary<int, BaseUnit> UnitList = new Dictionary<int, BaseUnit>();


        private static Random rRandomMe = new Random();

        public NetServerManager(Game game) 
            : base (game)
        {
            if (!IsInitialized)
            {
                LogManager.Write("NetServer: Starting up...");
                config = new NetPeerConfiguration("Main");
                config.Port = EngineManager.Settings.NetPort;
                config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);

                Server = new NetServer(config);
                Server.Start();

                IsInitialized = true;
            }
        }

        
        public override void Initialize()
        {
 	         base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
 	         base.Update(gameTime);

             if (IsInitialized)
             {
                 ReadMessage();
             }
        }

        public static void ReadMessage()
        {
            NetIncomingMessage msg;

            while ((msg = Server.ReadMessage()) != null)
            {
                switch (msg.MessageType)
                {
                    #region Debug Cases
                    case NetIncomingMessageType.DiscoveryRequest:
                        // just connect to first server discovered
                        NetOutgoingMessage testMessage = Server.CreateMessage();
                        testMessage.Write("Rebellion Server");
                        Server.SendDiscoveryResponse(testMessage, msg.SenderEndpoint);
                        Server.Connect(msg.SenderEndpoint);
                        break;
                    case NetIncomingMessageType.VerboseDebugMessage:
                    case NetIncomingMessageType.DebugMessage:
                    case NetIncomingMessageType.WarningMessage:
                    case NetIncomingMessageType.ErrorMessage:
                        LogManager.Write("NetServer Errors: "+ msg.ReadString());
                        break;
                    case NetIncomingMessageType.StatusChanged:
                        NetConnectionStatus status = (NetConnectionStatus)msg.ReadByte();
                        if (status == NetConnectionStatus.Connected)
                        {
                            //Send generated universe
                            
                        }
                        break;
                    #endregion
                    case NetIncomingMessageType.Data:
                        int CommandType = msg.ReadInt32();
                        #region Data
                        switch (CommandType)
                        {
                            case 0:
                                
                                break;
                            case 1:
                                int planID = msg.ReadInt32();
                                int refID = msg.ReadInt32();
                                int quantity = msg.ReadInt32();
                                ReceiveBuildOrder(planID, refID, quantity);
                                break;
                            case 2:
                                int planetID = msg.ReadInt32();
                                string type = msg.ReadString();
                                ReceiveCancelBuildOrder(planetID, type);
                                break;
                            case 3:
                                
                                break;
                            case 4:

                                break;
                            case 5:
                                //MoveUnit
                                break;
                            case 9:
                            //MultiplayerMessage();
                            case 10:
                                
                                break;
                            case 11:
                                break;
                            default:
                                break;
                        }
                        #endregion
                        break;
                }
                Server.Recycle(msg);
            }
            
        }

        public static void ReceiveBuildOrder(int PlanetID, int ReferenceID, int Quantity)
        {
            if (UnitList[ReferenceID] is Facility)
                gameUniverse.dUniverse[PlanetID].BuildFacilties(ReferenceID, Quantity, UnitList[ReferenceID].iConstructionCost);

            if (UnitList[ReferenceID] is Fighter)
                gameUniverse.dUniverse[PlanetID].BuildShips(ReferenceID, Quantity, UnitList[ReferenceID].iConstructionCost);

            if (UnitList[ReferenceID] is Troop)
                gameUniverse.dUniverse[PlanetID].BuildTroops(ReferenceID, Quantity, UnitList[ReferenceID].iConstructionCost);

            if (UnitList[ReferenceID] is CapitalShip)
                gameUniverse.dUniverse[PlanetID].BuildShips(ReferenceID, Quantity, UnitList[ReferenceID].iConstructionCost);
        }
        public static void ReceiveCancelBuildOrder(int PlanetID, string type)
        {
            switch(type)
            {
                case "Facilities":
                    gameUniverse.dUniverse[PlanetID].ClearFacilityBuild();
                    break;
                case "Troops":
                    gameUniverse.dUniverse[PlanetID].ClearTroopBuild();
                    break;
                case "Ships":
                    gameUniverse.dUniverse[PlanetID].ClearShipBuild();
                    break;
                default:
                    break;
            }
        }

        public static void SendCreatedUnit(int PlanetID, int ReferenceID, int InstanceID)
        {
            NetOutgoingMessage msg = Server.CreateMessage();
            msg.Write(2);
            msg.Write(PlanetID);
            msg.Write(ReferenceID);
            msg.Write(InstanceID);
            Server.SendMessage(msg, Server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
        }
        public static void SendNewFleet(int PlanetID, int fleetReferenceID, int fleetInstanceID, int capitalShipReferenceID, int capitalShipInstanceID)
        {
            NetOutgoingMessage msg = Server.CreateMessage();
            msg.Write(3);
            msg.Write(PlanetID);
            msg.Write(fleetReferenceID);
            msg.Write(fleetInstanceID);
            msg.Write(capitalShipReferenceID);
            msg.Write(capitalShipInstanceID);
            Server.SendMessage(msg, Server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
        }
        public static void SendTick()
        {
            NetOutgoingMessage msg = Server.CreateMessage();
            msg.Write(1);
            Server.SendMessage(msg, Server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
        }
                
        public static void SendGeneratedUniverse()
        {
            #region Generated Universe Sending
            foreach (var temp in gameUniverse.dUniverse)
            {
                NetOutgoingMessage omsg = Server.CreateMessage();
                omsg.Write(0);
                omsg.Write(temp.Key);
                omsg.Write(temp.Value.sName);
                omsg.Write(temp.Value.sTextureName);
                omsg.Write(temp.Value.sSectorName);
                omsg.Write(((int)temp.Value.vPosition.X));
                omsg.Write(((int)temp.Value.vPosition.Y));
                omsg.Write(temp.Value.bIsKeySystem);
                switch(temp.Value.eSectorType)
                {
                    case SectorType.Core:
                        omsg.Write(0);
                        break;
                    case SectorType.Mid:
                        omsg.Write(1);
                        break;
                    case SectorType.Rim:
                        omsg.Write(2);
                        break;
                }
                omsg.Write(temp.Value.iLoyaltyAlliance);
                omsg.Write(temp.Value.iLoyaltyEmpire);
                omsg.Write(temp.Value.iLoyaltySystem);
                omsg.Write(temp.Value.iNumEnergy);
                omsg.Write(temp.Value.iNumFacilities);

                switch (temp.Value.CurrentOwner)
                {
                    case TeamName.Empire:
                        omsg.Write(0);
                        break;
                    case TeamName.Alliance:
                        omsg.Write(1);
                        break;
                    case TeamName.Hutts:
                        omsg.Write(2);
                        break;
                    case TeamName.Smugglers:
                        omsg.Write(3);
                        break;
                    case TeamName.Default:
                        omsg.Write(4);
                        break;
                }

                if ((temp.Value.eSpecials & SystemSpecials.FacilityBonus) == SystemSpecials.FacilityBonus)
                    omsg.Write(1);
                else
                    omsg.Write(0);

                if ((temp.Value.eSpecials & SystemSpecials.ShipBonus) == SystemSpecials.ShipBonus)
                    omsg.Write(1);
                else
                    omsg.Write(0);

                if ((temp.Value.eSpecials & SystemSpecials.TroopBonus) == SystemSpecials.TroopBonus)
                    omsg.Write(1);
                else
                    omsg.Write(0);

                if ((temp.Value.eSpecials & SystemSpecials.JediBonus) == SystemSpecials.JediBonus)
                    omsg.Write(1);
                else
                    omsg.Write(0);

                foreach (var neighbor in temp.Value.lNeighbours)
                {
                    omsg.Write(1000);
                    omsg.Write(neighbor);
                }

                foreach (var troop in temp.Value.lTroop)
                {
                    omsg.Write(1001);
                    omsg.Write(troop.iReferenceID);
                    omsg.Write(troop.iUniqueID);
                }

                foreach (var fac in temp.Value.lFacilities)
                {
                    omsg.Write(1002);
                    omsg.Write(fac.iReferenceID);
                    omsg.Write(fac.iUniqueID);
                }

                foreach (var fighter in temp.Value.lFighter)
                {
                    omsg.Write(1003);
                    omsg.Write(fighter.iReferenceID);
                    omsg.Write(fighter.iUniqueID);
                }
                omsg.Write(1);
                Server.SendMessage(omsg, Server.Connections, NetDeliveryMethod.ReliableOrdered, 1);
            }
            NetOutgoingMessage endMessage = Server.CreateMessage();
            endMessage.Write(99);
            Server.SendMessage(endMessage, Server.Connections, NetDeliveryMethod.ReliableOrdered, 1);
            #endregion
        }
        public static void SendServerSettings(string a, string b, string c, string d, string e, string f, string g, string h, string i,
                                                    string j, string k, string l, string m, string n, bool o)
        {
            NetOutgoingMessage msg = Server.CreateMessage();
            msg.Write(1);
            msg.Write(a);
            msg.Write(b);
            msg.Write(c);
            msg.Write(d);
            msg.Write(e);
            msg.Write(f);
            msg.Write(g);
            msg.Write(h);
            msg.Write(i);
            msg.Write(j);
            msg.Write(k);
            msg.Write(l);
            msg.Write(m);
            msg.Write(n);
            msg.Write(o);
            foreach (NetConnection temp in Server.Connections)
            {
                Server.SendMessage(msg, temp, NetDeliveryMethod.ReliableUnordered, 0);
            }

        }

        /// <summary>
        /// Randomises the universe
        /// </summary>
        public static void GenerateUniverse()
        {
            int totalCore = 0, totalMid = 0, totalRim = 0;
            float iAlliancePlanets, iEmpirePlanets;

            gameUniverse = EngineManager.ContentManager.Load<Universe>("Content/XML/Universe");
            theTeams[0] = EngineManager.ContentManager.Load<Team>("Content/XML/Empire");
            theTeams[1] = EngineManager.ContentManager.Load<Team>("Content/XML/Alliance");
            theTeams[2] = EngineManager.ContentManager.Load<Team>("Content/XML/Hutts");
            theTeams[3] = EngineManager.ContentManager.Load<Team>("Content/XML/Smugglers");
            theTeams[4] = EngineManager.ContentManager.Load<Team>("Content/XML/Default");

            foreach (var team in theTeams)
            {
                var fakeTeam = team.ConvertToDictionary();
                foreach (var temp in fakeTeam)
                {
                    UnitList.Add(temp.Key, temp.Value);
                }
            }

            List<int> coreUnassignedPlanets = new List<int>();
            List<int> midUnassignedPlanets = new List<int>();
            List<int> rimUnassignedPlanets = new List<int>();

            switch (EngineManager.Settings.TeamFavoured)
            {
                case TeamName.Alliance:
                    iAlliancePlanets = 13; iEmpirePlanets = 7;
                    break;
                case TeamName.Empire:
                    iAlliancePlanets = 7; iEmpirePlanets = 13;
                    break;
                case TeamName.Default:
                    iAlliancePlanets = 5; iEmpirePlanets = 5;
                    break;
                default:
                    iAlliancePlanets = 10; iEmpirePlanets = 10;
                    throw new NotImplementedException("You Should Not Play with the Settings. Return to Default, Alliance or Empire. Will cause unknown results to continue");
            }

            if (EngineManager.Settings.DoubleStartingPlanets == true)
            {
                iAlliancePlanets *= 2;
                iEmpirePlanets *= 2;
            }

            foreach (KeyValuePair<int, RebSystem> temp in gameUniverse.dUniverse)
            {
                temp.Value.vPosition = new Vector2(temp.Value.vPosition.X*1.2f, -temp.Value.vPosition.Y*1.5f);

                #region Random NumFacs/Energy
                if (temp.Value.eSectorType == SectorType.Core)
                {
                    temp.Value.iNumFacilities = rRandomMe.Next(EngineManager.Settings.CoreMinFacilities, EngineManager.Settings.CoreMaxFacilities);
                    temp.Value.iNumEnergy = rRandomMe.Next(EngineManager.Settings.MinimumEnergy, temp.Value.iNumFacilities);
                    totalCore += 1;
                }

                if (temp.Value.eSectorType == SectorType.Mid)
                {
                    temp.Value.iNumFacilities = rRandomMe.Next(EngineManager.Settings.MidMinFacilities, EngineManager.Settings.MidMaxFacilities);
                    temp.Value.iNumEnergy = rRandomMe.Next(EngineManager.Settings.MinimumEnergy, temp.Value.iNumFacilities);
                    totalMid += 1;
                }

                if (temp.Value.eSectorType == SectorType.Rim)
                {
                    temp.Value.iNumFacilities = rRandomMe.Next(EngineManager.Settings.RimMinFacilities, EngineManager.Settings.RimMaxFacilities);
                    temp.Value.iNumEnergy = rRandomMe.Next(EngineManager.Settings.MinimumEnergy, temp.Value.iNumFacilities);
                    totalRim += 1;
                }
                #endregion
                #region Random Bonuses
                if ((EngineManager.Settings.ChanceJediBonus >= rRandomMe.Next(100)) && (temp.Value.eSpecials & SystemSpecials.JediBonus) != SystemSpecials.JediBonus)
                {
                    temp.Value.eSpecials |= SystemSpecials.JediBonus;
                }
                if ((EngineManager.Settings.ChanceShipBonus >= rRandomMe.Next(100)) && (temp.Value.eSpecials & SystemSpecials.ShipBonus) != SystemSpecials.ShipBonus)
                {
                    temp.Value.eSpecials |= SystemSpecials.ShipBonus;
                }
                if ((EngineManager.Settings.ChanceTroopBonus >= rRandomMe.Next(100)) && (temp.Value.eSpecials & SystemSpecials.TroopBonus) != SystemSpecials.TroopBonus)
                {
                    temp.Value.eSpecials |= SystemSpecials.TroopBonus;
                }
                if ((EngineManager.Settings.ChanceFacilityBonus >= rRandomMe.Next(100)) && (temp.Value.eSpecials & SystemSpecials.FacilityBonus) != SystemSpecials.FacilityBonus)
                {
                    temp.Value.eSpecials |= SystemSpecials.FacilityBonus;
                }
                #endregion
                #region Assign To Which Team
                switch (temp.Value.AssignTo)
                {
                    case TeamName.Alliance:
                        temp.Value.SetDiplomacy(TeamName.Alliance, 100);
                        if (temp.Value.eSectorType == SectorType.Core)
                            coreUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Mid)
                            midUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Rim)
                            rimUnassignedPlanets.Remove(temp.Key);
                        iAlliancePlanets--;
                        break;
                    case TeamName.Empire:
                        temp.Value.SetDiplomacy(TeamName.Empire, 100);
                        iEmpirePlanets--;
                        if (temp.Value.eSectorType == SectorType.Core)
                            coreUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Mid)
                            midUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Rim)
                            rimUnassignedPlanets.Remove(temp.Key);
                        break;
                    case TeamName.Hutts:
                        temp.Value.SetDiplomacy(TeamName.Hutts, 100);
                        if (temp.Value.eSectorType == SectorType.Core)
                            coreUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Mid)
                            midUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Rim)
                            rimUnassignedPlanets.Remove(temp.Key);
                        break;
                    case TeamName.Smugglers:
                        temp.Value.SetDiplomacy(TeamName.Smugglers, 100);
                        if (temp.Value.eSectorType == SectorType.Core)
                            coreUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Mid)
                            midUnassignedPlanets.Remove(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Rim)
                            rimUnassignedPlanets.Remove(temp.Key);
                        break;
                    case TeamName.Default:
                        if (temp.Value.eSectorType == SectorType.Core)
                            coreUnassignedPlanets.Add(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Mid)
                            midUnassignedPlanets.Add(temp.Key);
                        if (temp.Value.eSectorType == SectorType.Rim)
                            rimUnassignedPlanets.Add(temp.Key);
                        break;
                }
            }
            int randomTest;

            while (iEmpirePlanets + iAlliancePlanets > (coreUnassignedPlanets.Count + midUnassignedPlanets.Count + rimUnassignedPlanets.Count) / 3)
            {
                if (EngineManager.Settings.TeamFavoured == TeamName.Default)
                {
                    iEmpirePlanets--;
                    iAlliancePlanets--;
                }
                if (EngineManager.Settings.TeamFavoured == TeamName.Empire)
                {
                    iEmpirePlanets -=2;
                    iAlliancePlanets--;
                }
                if (EngineManager.Settings.TeamFavoured == TeamName.Alliance)
                {
                    iEmpirePlanets--;
                    iAlliancePlanets -= 2;
                }
            }

            for (int i = 0; i < iEmpirePlanets; i++)
            {
                if (i % 3 != 2)
                {
                    randomTest = rRandomMe.Next(coreUnassignedPlanets.Count);
                    gameUniverse.dUniverse[coreUnassignedPlanets[randomTest]].SetDiplomacy(TeamName.Empire, rRandomMe.Next(70, 100));
                    coreUnassignedPlanets.RemoveAt(randomTest);
                }
                else
                {
                    randomTest = rRandomMe.Next(midUnassignedPlanets.Count);
                    gameUniverse.dUniverse[midUnassignedPlanets[randomTest]].SetDiplomacy(TeamName.Empire, rRandomMe.Next(70, 100));
                    midUnassignedPlanets.RemoveAt(randomTest);
                }
            }

            for (int i = 0; i < iAlliancePlanets; i++)
            {
                if (i % 4 == 1)
                {
                    randomTest = rRandomMe.Next(coreUnassignedPlanets.Count);
                    gameUniverse.dUniverse[coreUnassignedPlanets[randomTest]].SetDiplomacy(TeamName.Alliance, 100);
                    coreUnassignedPlanets.RemoveAt(randomTest);
                }
                if (i % 4 == 2)
                {
                    randomTest = rRandomMe.Next(rimUnassignedPlanets.Count);
                    gameUniverse.dUniverse[rimUnassignedPlanets[randomTest]].SetDiplomacy(TeamName.Alliance, 100);
                    rimUnassignedPlanets.RemoveAt(randomTest);
                }
                else
                {
                    randomTest = rRandomMe.Next(midUnassignedPlanets.Count);
                    gameUniverse.dUniverse[midUnassignedPlanets[randomTest]].SetDiplomacy(TeamName.Alliance, rRandomMe.Next(70, 100));
                    midUnassignedPlanets.RemoveAt(randomTest);
                }
            }
                
            if (rimUnassignedPlanets.Count > 0)
            {
                foreach (var temp in rimUnassignedPlanets)
                {
                    gameUniverse.dUniverse[temp].SetDiplomacy(TeamName.Default, 80);
                }
            }

            if (coreUnassignedPlanets.Count > 0)
            {
                foreach (var temp in coreUnassignedPlanets)
                {
                    gameUniverse.dUniverse[temp].SetDiplomacy(TeamName.Default, 80);
                }
            }

            if (midUnassignedPlanets.Count > 0)
            {
                foreach (var temp in midUnassignedPlanets)
                {
                    gameUniverse.dUniverse[temp].SetDiplomacy(TeamName.Default, 80);
                }
            }
                #endregion
            #region Add Units to Planets
            foreach (var planet in gameUniverse.dUniverse)
            {
                Random test = new Random();

                switch (planet.Value.GetOwner())
                {
                    case TeamName.Alliance:
                        for (int i = 0; i < test.Next(6); i++)
                        {
                            planet.Value.lTroop.Add(new UnitInstance(10014));
                        }
                        break;
                    case TeamName.Empire:
                        planet.Value.lTroop.Add(new UnitInstance(20013));
                        planet.Value.lTroop.Add(new UnitInstance(20013));
                        for (int i = 0; i < test.Next(4); i++)
                        {
                            planet.Value.lTroop.Add(new UnitInstance(20015));
                        }
                        if (planet.Value.sName == "Coruscant")
                        {
                            planet.Value.lFacilities.Add(new UnitInstance(50001));
                        }
                        break;
                    case TeamName.Hutts:
                        for (int i = 0; i < test.Next(6); i++)
                        {
                            planet.Value.lTroop.Add(new UnitInstance(30001));
                        }
                        break;
                    case TeamName.Smugglers:
                        for (int i = 0; i < test.Next(6); i++)
                        {
                            planet.Value.lTroop.Add(new UnitInstance(40001));
                        }
                        break;
                    case TeamName.Default:
                        for (int i = 0; i < test.Next(6); i++)
                        {
                            planet.Value.lTroop.Add(new UnitInstance(50008));
                        }
                        for (int i = 0; i < test.Next(2); i++)
                        {
                            planet.Value.lTroop.Add(new UnitInstance(50009));
                        }
                        break;
                }
                if((planet.Value.eSpecials & SystemSpecials.FacilityBonus) == SystemSpecials.FacilityBonus)
                {
                    planet.Value.lFacilities.Add(new UnitInstance(50001));
                    planet.Value.lFacilities.Add(new UnitInstance(50001));
                }
                if((planet.Value.eSpecials & SystemSpecials.ShipBonus) == SystemSpecials.ShipBonus)
                {
                    planet.Value.lFacilities.Add(new UnitInstance(50005));
                    planet.Value.lFacilities.Add(new UnitInstance(50005));
                }
                if((planet.Value.eSpecials & SystemSpecials.TroopBonus) == SystemSpecials.TroopBonus)
                {
                    planet.Value.lFacilities.Add(new UnitInstance(50003));
                    planet.Value.lFacilities.Add(new UnitInstance(50003));
                }

            }
            #endregion
            Tick.TickTimerFinished += new Tick.Fire(GameTickTimer_TickTimerFinished);
        }

        static void GameTickTimer_TickTimerFinished()
        {
            SendTick();
            foreach (var planet in gameUniverse.dUniverse)
            {
                if (planet.Value.FacilityBuildQuantity > 0)
                {
                    int facilityProcessRate = 0;
                    foreach (var temp in planet.Value.lFacilities)
                    {

                        if ((UnitList[temp.GetReferenceID] as Facility).eType == FacilityType.Facilities)
                        {
                            facilityProcessRate += (UnitList[temp.GetReferenceID] as Facility).iProcessRate;
                        }
                    }

                    planet.Value.FacilityBuildCurrentProgress += facilityProcessRate + planet.Value.FacilityBuildOverflow;
                    if (planet.Value.FacilityBuildCurrentProgress > planet.Value.FacilityBuildTotalCost)
                    {
                        planet.Value.bJustBuiltFacility = true;
                        planet.Value.FacilityBuildQuantity--;
                        planet.Value.FacilityBuildOverflow = planet.Value.FacilityBuildCurrentProgress - planet.Value.FacilityBuildTotalCost;
                        planet.Value.FacilityBuildCurrentProgress = 0;
                    }
                }
                else
                {
                    planet.Value.ClearFacilityBuild();
                }

                if (planet.Value.TroopBuildQuantity > 0)
                {
                    int troopProcessRate = 0;
                    foreach (var temp in planet.Value.lFacilities)
                    {
                        if ((UnitList[temp.GetReferenceID] as Facility).eType == FacilityType.Troops)
                        {
                            troopProcessRate += (UnitList[temp.GetReferenceID] as Facility).iProcessRate;
                        }
                    }

                    planet.Value.TroopBuildCurrentProgress += troopProcessRate + planet.Value.TroopBuildOverflow;
                    if (planet.Value.TroopBuildCurrentProgress > planet.Value.TroopBuildTotalCost)
                    {
                        planet.Value.bJustBuiltTroop = true;
                        planet.Value.TroopBuildQuantity--;
                        planet.Value.TroopBuildOverflow = planet.Value.TroopBuildCurrentProgress - planet.Value.TroopBuildTotalCost;
                        planet.Value.TroopBuildCurrentProgress = 0;
                    }
                }
                else
                {
                    planet.Value.ClearTroopBuild();
                }

                if (planet.Value.ShipBuildQuantity > 0)
                {
                    int shipProcessRate = 0;
                    foreach (var temp in planet.Value.lFacilities)
                    {
                        if ((UnitList[temp.GetReferenceID] as Facility).eType == FacilityType.Ships)
                        {
                            shipProcessRate += (UnitList[temp.GetReferenceID] as Facility).iProcessRate;
                        }
                    }

                    planet.Value.ShipBuildCurrentProgress += shipProcessRate + planet.Value.ShipBuildOverflow;
                    if (planet.Value.ShipBuildCurrentProgress > planet.Value.ShipBuildTotalCost)
                    {
                        planet.Value.bJustBuiltShip = true;
                        planet.Value.ShipBuildQuantity--;
                        planet.Value.ShipBuildOverflow = planet.Value.ShipBuildCurrentProgress - planet.Value.ShipBuildTotalCost;
                        planet.Value.ShipBuildCurrentProgress = 0;
                    }
                }
                else
                {
                    planet.Value.ClearShipBuild();
                }

                #region Check Built Units
                if (planet.Value.bJustBuiltShip)
                {
                    planet.Value.bJustBuiltShip = false;
                    if (UnitList[planet.Value.ShipBuildReferenceID] is Fighter)
                    {
                        UnitInstance temporaryInstance = new UnitInstance(planet.Value.ShipBuildReferenceID);
                        planet.Value.lFighter.Add(temporaryInstance);
                        SendCreatedUnit(planet.Key, temporaryInstance.GetReferenceID, temporaryInstance.GetInstanceID);
                    }
                    if (UnitList[planet.Value.ShipBuildReferenceID] is CapitalShip)
                    {
                        CapitalShipInstance temporaryInstance = new CapitalShipInstance(planet.Value.ShipBuildReferenceID);
                        Fleet newFleet = new Fleet();
                        newFleet.AddShips(temporaryInstance);
                        planet.Value.lFleet.Add(newFleet);

                        SendNewFleet(planet.Key, newFleet.iReferenceID, newFleet.iUniqueID, temporaryInstance.GetReferenceID, temporaryInstance.GetInstanceID);
                    }
                }

                if (planet.Value.bJustBuiltTroop)
                {
                    UnitInstance temporaryInstance = new UnitInstance(planet.Value.TroopBuildReferenceID);
                    planet.Value.bJustBuiltTroop = false;
                    planet.Value.lTroop.Add(temporaryInstance);
                    SendCreatedUnit(planet.Key, temporaryInstance.GetReferenceID, temporaryInstance.GetInstanceID);
                }

                if (planet.Value.bJustBuiltFacility)
                {
                    planet.Value.bJustBuiltFacility = false;

                    UnitInstance temporaryInstance = new UnitInstance(planet.Value.FacilityBuildReferenceID);

                    planet.Value.lFacilities.Add(temporaryInstance);
                    SendCreatedUnit(planet.Key, temporaryInstance.GetReferenceID, temporaryInstance.GetInstanceID);

                }
            }
                #endregion
        }

    }
}
